﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using YXChatApiService.Application.AccountServices.Dtos;
using YXChatApiService.Application.BuddyServices.Dtos;
using YXChatApiService.Core.AccountEntity;
using YXChatApiService.Core.AccountEntity.DomainManager;
using YXChatApiService.Core.BuddyEntity;
using YXChatApiService.Core.BuddyEntity.DomainManager;
using YXChatApiService.HubCommon;

namespace YXChatApiService.Application.BuddyServices
{
    public class BuddyAppService:IBuddyAppService
    {
        private readonly IBuddyManager _buddyManager;
        private readonly IMapper _mapper;
        private readonly IAccountManager _accountManager;
        private readonly IHubContext<ChatHub,IChatService> _chatHub;

        public BuddyAppService(IBuddyManager buddyManager, IMapper mapper, IAccountManager accountManager, IHubContext<ChatHub, IChatService> chatHub)
        {
            _buddyManager = buddyManager;
            _mapper = mapper;
            this._accountManager = accountManager;
            _chatHub = chatHub;
        }
        public async Task<bool> CreateOrUpdateBuddy(BuddyCreateOrUpdateInput dto)
        {
            if (dto.Id.HasValue)
            {
                return await Update(dto);
            }
            else
            {
                return await Create(dto);
            }
        }

        public async Task<bool> DeleteBuddy(BuddyDto dto)
        {
             await _buddyManager.DeleteAsync(dto.Id);
             return true;
        }

        public async Task<List<BuddyAccountOutput>> GetBuddyAll(string accountNumber)
        {
            var selfBuddy= await _buddyManager.GetBuddyAll(accountNumber);
            var accounts = await _accountManager.QueryAsNoTracking.ToListAsync();
            var result = new List<BuddyAccountOutput>();
            Account account;
            foreach (var item in selfBuddy)
            {
                var output = new BuddyAccountOutput()
                {
                    IsAgree = true,
                    RefId = item.Id
                };
                account = item.AddeeAccountNumber == accountNumber ? 
                    accounts.FirstOrDefault(n => n.AccountNumber == item.AdderAccountNumber) 
                    : accounts.FirstOrDefault(n => n.AccountNumber == item.AddeeAccountNumber);
                output.Account = _mapper.Map<AccountDto>(account);
                result.Add(output);
            }
            return result.ToList();
        }

        public async Task<BuddyAccountOutput> SearchBuddyInfo(string selfNumber,string buddyNumber)
        {
            var buddy =await _buddyManager.GetBuddy(selfNumber,buddyNumber);
            var buddyAccount = _accountManager.GetAccount(buddyNumber);

            return new BuddyAccountOutput()
            {
                Account = _mapper.Map<AccountDto>(buddyAccount),
                IsAgree = buddy?.IsAgree ?? false,
            };
        }

        public async Task<List<BuddyAccountOutput>> GetNewBuddyList(string selfNumber)
        {
            var buddy=await _buddyManager.QueryAsNoTracking.Where(n =>
                    !n.IsAgree &&
                     n.AddeeAccountNumber == selfNumber)
                .ToListAsync();
            var accounts = await _accountManager.QueryAsNoTracking.ToListAsync();
            var result= from b in buddy join account in accounts on
                b.AdderAccountNumber equals account.AccountNumber 
                select new BuddyAccountOutput()
                {
                    Account = new AccountDto()
                    {
                        AccountNumber = account.AccountNumber,
                        Area = account.Area,
                        Avatar = account.Avatar,
                        NickName = account.NickName
                    },
                    RefId = b.Id
                };
            return result.ToList();
        }

        private async Task<bool> Create(BuddyCreateOrUpdateInput input)
        {
            input.CreateTime = DateTime.Now;
            input.Id = Guid.NewGuid();
            var entity =await _buddyManager.IsExistBuddy(input.AdderAccountNumber,input.AddeeAccountNumber);
            if (entity != null)
            {
                return false;
            }
            entity = _mapper.Map<Buddy>(input);
            await _buddyManager.InsertAsync(entity);
            return true;
        }

        private async Task<bool> Update(BuddyCreateOrUpdateInput input)
        {
            var entity = await _buddyManager.Get(input.Id.Value);
            if (entity == null)
            {
                return false;
            }
            entity.IsAgree = input.IsAgree;
            await _buddyManager.UpdateBuddy(entity);
            return true;
        }
    }
}